#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>


int main(int argc, char** argv)
{
    if(strcmp(argv[1], "-c") == 0)
    {
        // 压缩
        char* file_name = (char*)malloc(strlen(argv[2]) + 4);
        // strcpy(file_name, argv[1]);
        // strcat(file_name, ".dj");
        sprintf(file_name, "%s.dj", argv[2]);

        int fd1 = open(argv[2], O_RDONLY);
        int fd2 = open(file_name, O_WRONLY | O_CREAT | O_TRUNC, 0666);

        free(file_name);

        if(-1 == fd1)
        {
            perror("open fail");
            return 1;
        }

        char buf1[8];
        unsigned long long buf2 = 0;
        int ret;
        unsigned char filled_bit_cnt = 0;

        lseek(fd2, 1, SEEK_SET);

        while((ret = read(fd1, buf1, sizeof(buf1))) == 8)
        {
            buf2 = 0;

            for(int i = 0; i < 8; i++)
                buf2 |= (unsigned long long)(buf1[i] - 'a') << (i * 5);

            write(fd2, &buf2, 5);
        }

        if(ret > 0)
        {
            buf2 = 0;

            for(int i = 0; i < ret; i++)
                buf2 |= (unsigned long long)(buf1[i] - 'a') << (i * 5);

            write(fd2, &buf2, ret * 5 / 8 + 1);

            filled_bit_cnt = 8 - ret * 5 % 8;
            lseek(fd2, 0, SEEK_SET);
            write(fd2, &filled_bit_cnt, 1);
        }
        else if(ret == 0)
        {
            lseek(fd2, 0, SEEK_SET);
            write(fd2, &filled_bit_cnt, 1);        
        }

        close(fd1);
        close(fd2);
    }
    else if(strcmp(argv[1], "-x") == 0)
    {
        // 解压
        char* p = strstr(argv[2], ".dj");

        if(NULL == p)
        {
            fprintf(stderr, "文件格式错误！\n");
            exit(1);
        }

        char* file_name = (char*)calloc(strlen(argv[2]) - 2, 1);
        strncpy(file_name, argv[2], strlen(argv[2]) - 3);

        int fd1 = open(argv[2], O_RDONLY);
        int fd2 = open(file_name, O_WRONLY | O_CREAT | O_TRUNC, 0666);

        free(file_name);

        if(-1 == fd1)
        {
            perror("open fail");
            return 1;
        }

        unsigned char filled_bit_cnt;
        read(fd1, &filled_bit_cnt, 1);

        unsigned long long buf1;
        char buf2[8];
        int ret;
        struct stat st;
        fstat(fd1, &st);
        int file_size = st.st_size;
        printf("%d\n", file_size);
        file_size -= 1;
        int n = file_size / 5;
        if(file_size % 5 == 0) n -= 1;

        for(int i = 0; i < n; i++)
        {
            ret = read(fd1, &buf1, 5);

            for(int i = 0; i < 8; i++)
            {
                buf2[i] = ((buf1 >> (i * 5)) & 0x1F) + 'a';
            }

            write(fd2, buf2, sizeof(buf2));         
        }

        ret = read(fd1, &buf1, 5);
        
        n = (ret * 8 - filled_bit_cnt) / 5;

        for(int i = 0; i < n; i++)
        {
            buf2[i] = ((buf1 >> (i * 5)) & 0x1F) + 'a';
        }

        write(fd2, buf2, n);  

        close(fd1);
        close(fd2);
    }

    return 0;
}

